package cc.ilzy.mall.product.service.impl;

import cc.ilzy.mall.constants.CommonConstants;
import cc.ilzy.mall.model.pojo.Product;
import cc.ilzy.mall.model.pojo.User;
import cc.ilzy.mall.model.request.CartItemRequest;
import cc.ilzy.mall.model.vo.CartItemVO;
import cc.ilzy.mall.model.vo.CartVO;
import cc.ilzy.mall.product.interceptors.UserLoginInterceptor;
import cc.ilzy.mall.product.service.ICartService;
import cc.ilzy.mall.product.service.IProductService;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class CartService implements ICartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IProductService productService;

    @Override
    public void addToCart(CartItemRequest cartItemRequest) {
        long productId = cartItemRequest.getProductId();
        int buyNum = cartItemRequest.getBuyNum();
        // 获取购物车
        BoundHashOperations<String, Object, Object> myCart = getMyCartOpt();

        Object cacheObj = myCart.get(productId);
        String result = "";
        if (cacheObj != null) {
            result = (String) cacheObj;
        }
        if (StrUtil.isNotBlank(result)) {
            // 已存在则更新数量
            CartItemVO cartItemVO = JSONUtil.toBean(result, CartItemVO.class);
            cartItemVO.setBuyNum(buyNum);
            result = JSONUtil.toJsonStr(cartItemVO);
        } else {
            // 不存在则新建一个商品
            Product product = productService.getById(cartItemRequest.getProductId());
            CartItemVO cartItemVO = new CartItemVO();
            cartItemVO.setProductId(productId)
                      .setBuyNum(buyNum)
                      .setAmount(product.getAmount())
                      .setProductImg(product.getCoverImg())
                      .setProductTitle(product.getTitle())
                      .setTotalAmount(product.getAmount().multiply(new BigDecimal(buyNum)));
            result = JSONUtil.toJsonStr(cartItemVO);
        }
        myCart.put(productId, result);
    }

    @Override
    public void changeItemNum(CartItemRequest cartItemRequest) {
        addToCart(cartItemRequest);
    }

    @Override
    public void clear() {
        BoundHashOperations<String, Object, Object> myCart = getMyCartOpt();
        myCart.delete(myCart.keys());
        // 清空购物车
        redisTemplate.delete(getCartKey());
    }

    @Override
    public CartVO getMyCart() {
        List<CartItemVO> carts = buildCartItem(true);
        return new CartVO().setCartItems(carts);

    }

    /**
     * 构建购物车项
     *
     * @param isUpdatePrice 是否更新最新价格
     * @return
     */
    private List<CartItemVO> buildCartItem(boolean isUpdatePrice) {
        BoundHashOperations<String, Object, Object> myCart = getMyCartOpt();
        List<Object> values = myCart.values();
        List<CartItemVO> cartItemVOS = Objects.requireNonNull(values).stream()
                                              .map(obj -> JSONUtil.toBean(obj.toString(), CartItemVO.class))
                                              .collect(Collectors.toList());
        if(isUpdatePrice) {
            List<Long> ids = cartItemVOS.stream().mapToLong(CartItemVO::getProductId).boxed().toList();
            refreshQueryPrice(ids, cartItemVOS);
        }
        return cartItemVOS;
    }

    private void refreshQueryPrice(List<Long> ids, List<CartItemVO> cartItemVOS) {
        productService.listByIds(ids).forEach(product -> {
            cartItemVOS.stream()
                       .filter(cartItem -> cartItem.getProductId().equals(product.getId()))
                       .forEach(cartItem -> {
                           cartItem.setAmount(product.getAmount());
                           cartItem.setTotalAmount(product.getAmount().multiply(new BigDecimal(cartItem.getBuyNum())));
                       });
        });
    }

    @Override
    public void deleteItem(long productId) {
        BoundHashOperations<String, Object, Object> myCart = getMyCartOpt();
        myCart.delete(productId);
    }

    private BoundHashOperations<String, Object, Object> getMyCartOpt() {
        return redisTemplate.boundHashOps(getCartKey());

    }

    private String getCartKey() {
        User user = UserLoginInterceptor.getCurrentUser();
        return String.format(CommonConstants.CacheKey.CART_KEY, user.getId());
    }
}
